import store from '@/store'
import config from '../config'
import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import { toast, showConfirm, tansParams } from '@/utils/common'
import { encryptBase64, encryptWithAes, generateAesKey, decryptWithAes, decryptBase64 } from '@/utils/crypto';
import { encrypt, decrypt } from '@/utils/jsencrypt';

let timeout = 10000
const baseUrl = config.baseUrl || 'http://localhost:8080';
const clientId = config.clientId || '';

export const request = (options) => {
    return new Promise((resolve, reject) => {
        const token = uni.getStorageSync('token');
        options.url = (options.baseUrl || baseUrl) + options.url;
        // 兼容不同调用方使用 options.headers (axios 风格) 或 options.header (uni.request 风格)
        if (options.headers && !options.header) {
            options.header = options.headers;
        } else if (options.headers && options.header) {
            options.header = {
                ...options.header,
                ...options.headers
            };
        }
        options.header = {
            ...options.header,
            clientid: clientId
        };
        if (token) {
            options.header = {
                Authorization: 'Bearer ' + token,
                ...options.header
            };
        }
        // 默认 Content-Type
        // 注意：在某些运行环境中（比如部分小程序或 node 环境）全局可能没有 FormData，
        // 直接引用会抛出 ReferenceError，因此先判断全局是否存在 FormData
        const hasFormData = (typeof FormData !== 'undefined');
        if (!options.header['Content-Type'] && !(hasFormData && options.data instanceof FormData)) {
            options.header['Content-Type'] = 'application/json;charset=utf-8';
        }

        // 是否需要加密（优先使用 options.isEncrypt 布尔，其次兼容 header 中的字符串 'true'）
        const method = (options.method || 'GET').toLowerCase();
        const isEncrypt = options.isEncrypt === true || (options.header && String(options.header.isEncrypt) === 'true');
        if (isEncrypt && (method === 'post' || method === 'put')) {
            try {
                // 生成 AES key（WordArray）
                const aesKey = generateAesKey();
                // RSA 加密传输：先将 aesKey base64 编码，再用 RSA 公钥加密
                const base64Key = encryptBase64(aesKey);
                const encryptedKey = encrypt(base64Key);
                if (encryptedKey) {
                    options.header['encrypt-key'] = encryptedKey;
                }
                // 使用 AES 对请求体进行加密
                if (options.data !== undefined) {
                    options.data = typeof options.data === 'object' ? encryptWithAes(JSON.stringify(options.data), aesKey) : encryptWithAes(options.data, aesKey);
                }
            } catch (e) {
                console.warn('request encrypt failed', e);
            }
        }
        // 临时调试：打印即将发送的 headers 和 data（便于确认 encrypt-key 与加密后的 body）
        console.info('[request] sending', {
            url: options.url,
            method: options.method || 'GET',
            header: options.header,
            data: options.data
        })

        uni.request({
            ...options,
            success(res) {
                if (res.statusCode === 200) {
                    // 响应解密：检查响应头中是否包含 encrypt-key（大小写兼容）
                    try {
                        const headers = res.header || {};
                        let keyStr = null;
                        for (const k in headers) {
                            if (k && k.toLowerCase() === 'encrypt-key') {
                                keyStr = headers[k];
                                break;
                            }
                        }
                        if (keyStr) {
                            // 使用 RSA 私钥解密得到 base64 字符串，再 base64 解析为 aesKey（WordArray）
                            const base64Str = decrypt(keyStr);
                            if (base64Str) {
                                const aesKey = decryptBase64(base64Str);
                                const decrypted = decryptWithAes(res.data, aesKey);
                                if (decrypted) {
                                    try {
                                        const parsed = JSON.parse(decrypted);
                                        resolve(parsed);
                                        return;
                                    } catch (e) {
                                        // 不是 JSON，直接返回解密后的字符串
                                        resolve(decrypted);
                                        return;
                                    }
                                }
                            }
                        }
                    } catch (e) {
                        console.warn('response decrypt failed', e);
                    }
                    // 默认返回原始 res.data
                    resolve(res.data);
                } else {
                    reject(res.errMsg || res.data || res);
                }
            },
            fail(err) {
                reject(err);
            }
        });
    });
};
